﻿#include "xcast_handler.h"
#include "base.h"

using namespace xcast;

int xcast_handler_channel_stat_tips(void* user_data, xcast_data& e) {
  xcast_data evt(e);
  const char* tips;

  tips = evt["tips"];

  Context::XcastEvent::OnTips(tips);
  return XCAST_OK;
}

/* xcast event */
int xcast_handler_xcast_event(void* user_data, xcast_data& e) {
  const char* err_msg;
  int err;
  xcast_data evt(e);
  err = evt["err"];
  err_msg = evt["err-msg"];

  Context::XcastEvent::OnError(err, err_msg);
  return XCAST_OK;
}

int xcast_handler_stream_event(void* user_data, xcast_data& e) {
  xcast_data evt(e);
  int32_t clazz = evt["class"];
  int32_t format = evt["format"];

  switch (clazz) {
    case xc_stream_audio:
      if (xc_stream_added == (int) evt["type"]) {
        if (xc_stream_out == (int) evt["direction"]) {
          Stream::Audio::XcastEvent::OnAdd(evt["src"], true, evt["uin"], true);
        } else if (xc_stream_in == (int) evt["direction"]) {
          Stream::Audio::XcastEvent::OnAdd(evt["src"], false, evt["uin"], true);
        }
      } else if (xc_stream_removed == (int) evt["type"]) {
        if (xc_stream_out == (int) evt["direction"]) {
          Stream::Audio::XcastEvent::OnAdd(evt["src"], true, evt["uin"], false);
        } else if (xc_stream_in == (int) evt["direction"]) {
          Stream::Audio::XcastEvent::OnAdd(evt["src"], false, evt["uin"], false);
        }
      } else if (xc_stream_updated == (int) evt["type"]) {
        Stream::Audio::XcastEvent::OnUpdate(evt["src"], evt["uin"], evt["state"]);
      }
      break;
    case xc_stream_video:
      if (xc_stream_added == (int) evt["type"]) {
        if (xc_stream_out == (int) evt["direction"]) {
          Stream::Video::XcastEvent::OnAdd(evt["src"], true, evt["uin"], true);
        } else if (xc_stream_in == (int) evt["direction"]) {
          Stream::Video::XcastEvent::OnAdd(evt["src"], false, evt["uin"], true);
        }
      } else if (xc_stream_removed == (int) evt["type"]) {
        if (xc_stream_out == (int) evt["direction"]) {
          Stream::Video::XcastEvent::OnAdd(evt["src"], true, evt["uin"], false);
        } else if (xc_stream_in == (int) evt["direction"]) {
          Stream::Video::XcastEvent::OnAdd(evt["src"], false, evt["uin"], false);
        }
      } else if (xc_stream_updated == (int) evt["type"]) {
        Stream::Video::XcastEvent::OnUpdate(evt["src"], evt["uin"], evt["state"]);
      } else if (xc_stream_media == (int)evt["type"]) {
        if (xc_media_argb32 == format) {
          Stream::Video::XcastEvent::OnVideoFrame(evt["uin"], const_cast<uint8_t*>(evt["data"].bytes_val()), evt["size"], evt["format"], evt["width"], evt["height"], evt["rotate"], evt["src"]);
        } else if (xc_media_layer == format) {
          uint32_t size = evt["data"].size();
          for (uint32_t i = 0; i < size; i++) {
            auto layer = evt["data"].at(i);
            Stream::Video::XcastEvent::OnVideoLayer(i, layer["size"], const_cast<uint8_t*>(layer["data"].bytes_val()), (uint8_t)layer["format"], (uint8_t)layer["blend-mode"],
              layer["left"], layer["top"], layer["width"], layer["height"], layer["container-width"], layer["container-height"],
              evt["uin"], layer["visible"], evt["src"]);
          }
        }
      }
      break;
    default:
      break;
  }

  bool active = (bool)evt["active"];
  bool quality = (int)evt["quality"] > 0;
  int state = (int)evt["state"];
    
    if ( xc_stream_running == state && active == false) {
        Stream::Network::XcastEvent::OnStreamActive(evt["src"], evt["uin"], active);
    }
    
    if (xc_stream_running == state && quality == false) {
        Stream::Network::XcastEvent::OnNetworkState(evt["src"], evt["uin"],quality);
    }
    
  return XCAST_OK;
}

int xcast_handler_device_event(void* user_data, xcast_data& e) {
  xcast_data evt(e);
  switch ((int) evt["class"]) {
    case xc_device_camera: {
      if (xc_device_added == (int) evt["type"]) {
        Device::Video::XcastEvent::OnAddCamera(evt["src"], true);
      } else if (xc_device_removed == (int) evt["type"]) {
        Device::Video::XcastEvent::OnAddCamera(evt["src"], false);
      } else if (xc_device_updated == (int) evt["type"]) {
        Device::Video::XcastEvent::OnCameraUpdate(evt["src"], evt["state"]);
      } else if (xc_device_preview == (int) evt["type"]) {
        Device::Video::XcastEvent::OnCameraPreview(evt["src"], (uint8_t*)evt["data"].bytes_val(),
                                                   evt["size"], evt["format"], evt["width"],
                                                   evt["height"]);
      }
    }
      break;
    case xc_device_screen_capture:
      break;
    case xc_device_mic: {
      if (xc_device_added == (int) evt["type"]) {
        Device::Audio::XcastEvent::OnAddMic(evt["src"], true);
      } else if (xc_device_removed == (int) evt["type"]) {
        Device::Audio::XcastEvent::OnAddMic(evt["src"], false);
      } else if (xc_device_updated == (int) evt["type"]) {

      }
    }
      break;
    case xc_device_speaker: {
      if (xc_device_added == (int) evt["type"]) {
        Device::Audio::XcastEvent::OnAddSpeaker(evt["src"], true);
      } else if (xc_device_removed == (int) evt["type"]) {
        Device::Audio::XcastEvent::OnAddSpeaker(evt["src"], false);
      } else if (xc_device_updated == (int) evt["type"]) {

      }
    }
      break;
    case xc_device_external:
      break;
    default:
      break;
  }

  return XCAST_OK;
}

/* stream event call back */
int xcast_handler_channel_event(void* user_data, xcast_data& e) {
  xcast_data evt(e);

  switch ((int) evt["type"]) {
    case xc_channel_added:
      Channel::XcastEvent::OnConnecting(evt["src"]);
      break;
    case xc_channel_updated:
      if (evt["state"] == xc_channel_connected) {
        Channel::XcastEvent::OnConnected(evt["src"]);
      }
      break;
    case xc_channel_removed:
      Channel::XcastEvent::OnDisconnected(evt["src"], evt["err"], evt["err-msg"]);
      break;
    default:
      break;
  }

  return XCAST_OK;
}
